
var Widget = Widget || {};

Widget.Control = { };

(function(){
	
	var _memorizer = function() {
		return Widget.Memorizer.instance();
	}
	
	var _config = function() {
		return Widget.Config.instance();
	}
	
	var _uiManager = function() {
		return Widget.UIManager.instance();
	}
	var _unitManager = function() {
		return Widget.UnitManager.instance();
	}
	var _configView = function() {
		return Widget.UI.Config.instance();
	}
	var _unitEditView = function () {
		return Widget.UI.UnitEdit.instance();
	}
	
	var _questionView = function() {
		return Widget.UI.QuestionView.instance();
	}
	
	var _questionListView = function() {
		return Widget.UI.QuestionListView.instance();
	}
	
	var _dockedView = function() {
		return Widget.UI.Docked.instance();
	}
	
	var _challengeView = function() {
		return Widget.UI.ChallengeView.instance();
	}
	
	var _refreshConfigView = function() {
		_configView().updateModel( {
			'units' : _unitManager().list(),
			'config' : {
				'autoChallengeTime' : _config().autoChallengeTime(),
				'autoHide': _config().autoHide()
			}
		});
	}
	
	var _refreshUnitView = function(edit, unit) {
		// Refactor it
		//_unitEditView().edit(edit);
		
		if (!edit && typeof(unit) == 'undefined') {
			unit = Widget.Unit.create("", _unitManager().types()[0].type);
		}
		_unitEditView().updateModel(unit);
		_unitEditView().edit(edit);
	}
	
	var _refreshQuestionView = function(edit, item) {
		_questionView().edit(edit);
		if (!_questionView().isEdit()) {
			item = new Widget.Unit.Item("", []);
		}
		_questionView().updateModel(item);
	}
	
	var _refreshQuestionListView = function(unit) {
		_questionListView().updateModel(unit);
		if (_questionListView().itemsSize() > 0) {
			_questionListView().selectRow(0);
		}
	}
	
	var _refreshDockedView = function() {
		
		_dockedView().updateModel(_unitManager().list());
		
	}
	
	var _refreshChallengeView = function(result, question) {
		_challengeView().answered(result);
		if (_challengeView().isAnswered()) {
		}
		_challengeView().updateModel(question);
	}
	
	var _refreshOnBack = function() {
		
		if (_uiManager().current() == _configView()) {
			_refreshConfigView();
		}
		
	}
	
	var _configureChallenge = function() {

		var unitName = $("#dockedView #unitSelector :selected").val();
		_memorizer().unit(_unitManager().get(unitName));
		
	}
	
	var _nextChallenge = function(autoChallenge) {
		
		var nextQuestion = _memorizer().next();
		_refreshChallengeView(false, {
			'autoChallenge': (typeof(autoChallenge) != 'undefined' && autoChallenge) ? true : false, 
			'question' : nextQuestion.question,
			'correctAnswers' : nextQuestion.answers,
			'stat' : _memorizer().stat(),
			'answer' : ''
		});
		
	}
	
	var _hideFeedbacks = function() {
		Widget.Feedback.hideAll();
	}
	
	var _startSchedule = function() {
		if (!_memorizer().isScheduled()) {
			$('#dockedView #unitSelector').attr('disabled', 'true');
			
			_configureChallenge();
			_memorizer().startSchedule();
		}
	}
	
	var _stopSchedule = function() {
		if (_memorizer().isScheduled()) {
			$('#dockedView #unitSelector').removeAttr('disabled');
			_memorizer().stopSchedule();
		}
	}
	
	var _reSchedule = function() {
		if (_memorizer().isScheduled()) {
			_memorizer().reSchedule();
		}
	}
	
	var _init_validationMessages = function() {
		
		$.extend($.validationEngineLanguage.allRules, {
			'unitEditView.validateUnit' : {
				'alertText' : Widget.Messages['Validators.UnitEditView.ValidateUnit.text'] 
					//'* Unit must have'
			},
			'dockedView.validateUnit': {
				'alertText' : Widget.Messages['Validators.DockedView.ValidateUnit.text']
			},
			'configView.validateAutoTime': {
				'alertText' : Widget.Messages['Validators.ConfigView.ValidateAutoTime.text']
			},
			'challengeView.validateAnswer': {
				'alertText' : Widget.Messages['Validators.ChallengeView.ValidateAnswer.Wrong.text']
			}
		});
		
	}
	
	var _init_controls = function() {
		
		_hideFeedbacks();
		
		// Close button
		$(".closeButton").unbind('click');
		$(".closeButton").click(function() {
			_uiManager().close();
		});
		
		$(".backButton").unbind('click');
		$(".backButton").click(function() {
			
			_uiManager().back(_init_controls);
			_refreshOnBack();
			
		});
		
		_init_InitDockedViewControls();
		
		// FIXME: add title
		
		addTooltip('.closeButton', Widget.Messages['Buttons.CloseButton.text']);
		addTooltip('.backButton', Widget.Messages['Buttons.BackButton.text']);
		addTooltip('.hideButton', Widget.Messages['Buttons.HideButton.text']);
		addTooltip('.configButton', Widget.Messages['Buttons.ConfigButton.text']);
		addTooltip('.autoChallengeButton', function() {
			
			return _memorizer().isScheduled() ? Widget.Messages['Buttons.AutoChallengeButtonOff.text'] : Widget.Messages['Buttons.AutoChallengeButtonOn.text'];
			
		});
		addTooltip('.challengeButton', Widget.Messages['Buttons.ChallengeButton.text']);
		
		function addTooltip(selector, tooltip) {
			$(selector).hover(
					  function () {
						var tooltipText; 
						if (typeof(tooltip) == 'function') {
							tooltipText = tooltip();
						} else {
							tooltipText = tooltip;
						}
					    $('.controlTooltip').append('<span> ' + tooltipText + '</span>');
					  }, 
					  function () {
					    $('.controlTooltip').html('');
					  }
			);
		}
	}
	
	var _init_InitDockedViewControls = function() {
		
		/*
		 * Docked view
		 */ 
		$("#dockedView .configButton").unbind('click');
		$("#dockedView .configButton").click(function() {
			
			_stopSchedule();
			_refreshConfigView();
			_uiManager().show(_configView(), false, _init_controls);
			
		});
		
		$("#dockedView .challengeButton").unbind('click');
		$("#dockedView .challengeButton").click(function() {
			
			if (validateUnitSelector()) {
				_configureChallenge();
				
				_nextChallenge();
				_uiManager().show(_challengeView(), false, _init_controls);
			}
			
		});
		
		$("#dockedView .autoChallengeButton").unbind('click');
		$("#dockedView .autoChallengeButton").click(function() {
			
			if (validateUnitSelector()) {
				if (!_memorizer().isScheduled()) {
					_startSchedule();
				} else {
					_stopSchedule();
				}
				toggleAutoChallenge();
			}
			
		});
		
		$("#dockedView .hideButton").unbind('click');
		$("#dockedView .hideButton").click(function() {
			
			widget.hide();
			
		});
		
		
		
		
		toggleAutoChallenge();
		
		function validateUnitSelector() {
			$('#dockedView form[0]').validationEngine();
			
			var validators = [];
			validators.push({
				'selector': '#dockedView #unitSelector',
				'rules': [{
					'name': 'dockedView.validateUnit',
					'type': 'func',
					'fn': validateUnit
				}]
			});
				
			var isValid = Widget.Validator.validate(validators, {
				'align': Widget.Feedback.ALIGN_TOP_LEFT
			});

			function validateUnit() {
				return (_dockedView().model.length <= 0);
			}
			
			return isValid;
		}
		function toggleAutoChallenge() {
			if (!_memorizer().isScheduled()) {
				$("#dockedView .autoChallengeButton").removeClass('docked');
			} else {
				$("#dockedView .autoChallengeButton").addClass('docked');
			}
		}
		
	}
	
	var _init_dockedViewControls = function() {
	}
	
	var _init_configViewControls = function() {
		
		/*
		 * Config view
		 */
		$("#configView #addUnit").unbind('click');
		$("#configView #addUnit").click(function() {
			
			_refreshUnitView(false);
			_uiManager().show(_unitEditView(), true, _init_controls);
			
		});
		
		$("#configView #editUnit").unbind('click');
		$("#configView #editUnit").click(function() {
			
			if (anySelectableUnit()) {
				_refreshUnitView(true, _unitManager().get($("#configView #unitList :selected").val()));
				_uiManager().show(_unitEditView(), true, _init_controls);
			}
			
		});
		
		$("#configView #removeUnit").unbind('click');
		$("#configView #removeUnit").click(function() {
			
			// Remove unit form unit manager
			if (anySelectableUnit()) {
				_unitManager().remove($("#configView #unitList :selected").val());
				_refreshConfigView();
			}
			
		});
		
		$("#configView button#saveConfig").unbind('click');
		$("#configView button#saveConfig").click(function() {
			
			// Validation
			
			var autoChallengeTime = $('#configView #autoChallengeTime').val();
			var autoHide = $('#configView #autoHide').is(':checked');
			
			if (validateConfig()) {
				_config().autoChallengeTime(autoChallengeTime);
				_config().autoHide(autoHide);
				
				_refreshDockedView();
				_uiManager().show(_dockedView(), false, _init_controls);
			}
			
		});
		
		function validateConfig() {
			$('#configView form[0]').validationEngine();
			
			var validators = [];
			var autoChallengeTime = $('#configView #autoChallengeTime').val();
			validators.push({
				'selector': '#configView #autoChallengeTime',
				'rules': ['required', {
					'name': 'configView.validateAutoTime',
					'type': 'func',
					'fn': validateAutoTime
				}]
			});
				
			var isValid = Widget.Validator.validate(validators, {
				'align': Widget.Feedback.ALIGN_TOP_LEFT
			});

			function validateAutoTime() {
				var iAutoChallengeTime = parseInt(autoChallengeTime);
				return !(iAutoChallengeTime >= 1 && iAutoChallengeTime <= 1440); 
			}
			
			return isValid;
		}
		
		function anySelectableUnit() {
			return (_configView().model.units != null && _configView().model.units.length > 0);
		}

	}
	
	var _init_unitViewControls = function() {
		/*
		 * Unit view
		 */
		
		$("#unitEditView select#unitType").unbind('change');
		$("#unitEditView select#unitType").change(function() {
			
			var unitName = $("#unitEditView input#unitName").val();
			var unitType = $("#unitEditView select#unitType").val();

			_cleanMountPoints();
			
			var unit = Widget.Unit.create(unitName, unitType);
			_refreshUnitView(false, unit);
			
		});
		
		$("#unitEditView button#fileChooser").unbind('click');
		$("#unitEditView button#fileChooser").click(function() {
			
			var unitName = $("#unitEditView input#unitName").val();
			
			if (_unitEditView().model.file() != null) {
				_cleanMountPoints([_unitEditView().model.file()]);
			} else {
				_cleanMountPoints();
			}
			var mountPath = 'unit-' + (_lastUnitMountId() + 1);
			
			opera.io.filesystem.browseForSave(mountPath, '', saveFileCallback, true);
			function saveFileCallback(file) {
				if (file) {
					_unitEditView().model.name = unitName;
					_unitEditView().model.configure(file.path);
					_refreshUnitView(false, _unitEditView().model);
				}
			}			
			
		});
		
		
		$("#unitEditView button#saveUnit").unbind('click');
		$("#unitEditView button#saveUnit").click(function() {
			
			var unitName = $("#unitEditView input#unitName").val();
			var unitType = $("#unitEditView select#unitType").val();
			
			$('#unitEditView form[0]').validationEngine();
			var validData = Widget.Validator.validate(_unitValidators(), {
				'align': Widget.Feedback.ALIGN_TOP_LEFT
			});
			
			if (validData) {
				
				var unit = null;
				if (!_unitEditView().isEdit()) {
					unit  = _unitEditView().model;
					unit.name = unitName;
					
					// model update
					if (unitType == 'fileStore') {
					}
					
					_unitManager().add(unit);
					
					_refreshUnitView(true, unit);
					
				} else {
					unit = _unitManager().get(unitName);
					_unitManager().update(unit);
					
					_uiManager().back(_configView(), _init_controls);
					_refreshOnBack();
				}
				
			}
			
		});
		
		$("#unitEditView button#listQuestions").unbind('click');
		$("#unitEditView button#listQuestions").click(function() {
			
			_refreshQuestionListView(_unitEditView().model);
			_uiManager().show(_questionListView(), true, _init_controls);
			
		});
		
		function _lastUnitMountId() {
			
			// Adjust mount point
			var lastUnitMountId = 0;
			var mountPoints = opera.io.filesystem.mountPoints;
			for (var i = 0, mountPoint; mountPoint = mountPoints[i]; i++) {
				if (mountPoint.path.indexOf('mountpoint://unit-') == 0) {
					var currentUnitMountId = parseInt(mountPoint.path.substring('mountpoint://unit-'.length));
					if (lastUnitMountId < currentUnitMountId) {
						lastUnitMountId = currentUnitMountId;
					}
				}
				
			}
			
			return lastUnitMountId;
			
		}
		
		function _cleanMountPoints(excludes) {
			// Find last used mount point id
			
			var mountPointsToRemove = [];
			var units = _unitManager().list();
			var mountPoints = opera.io.filesystem.mountPoints;
			
			for (var i = 0; i < mountPoints.length; i++) {
				
				
				var mountPoint = mountPoints[i];
				
				var skip = false;
				if (typeof(excludes) != 'undefined') {
					for (var j = 0; j < excludes.length; j++) {
						if (mountPoint == excludes[j]) {
							skip = true;
							break;
						}
					}
				}
				
				if (mountPoint.path.indexOf('mountpoint://unit-') == 0 && !skip) {
					
					var removeMountPoint = true;
					for (var j = 0; j < units.length; j++) {
						
						var unit = units[j];
						if (unit.type == 'fileStore') {
							
							if (mountPoint.path == unit.file()) {
								removeMountPoint = false;
								break;
							}
						}
						
					}
					
					if (removeMountPoint) {
						mountPointsToRemove.push(mountPoint);
					}
				}
				
			}
			
			for (var i = 0; i < mountPointsToRemove.length; i++) {
				opera.io.filesystem.removeMountPoint(opera.io.filesystem.mountPoints.resolve(mountPointsToRemove[i]));
			}
			
		}
		
		function _unitValidators() {
			
			var unitName = $("#unitEditView input#unitName").val();
			var unitType = $("#unitEditView select#unitType").val();
			
			// General validators
			var validators = [];
			
			if (!_unitEditView().isEdit()) {
				validators.push({
					'selector': '#unitEditView input#unitName',
					'rules': ['required', 'onlyLetter', {
						'name': 'unitEditView.validateUnit',
						'type': 'func',
						'fn': validateUnit
					}]
				});
				
				// File store validators
				if (unitType == 'fileStore') {
					validators.push({
						'selector': '#unitEditView input#fileName',
						'rules': ['required' ]
					});
				}
			}
			
			function validateUnit() {
				return _unitManager().contains(unitName);
			}
			
			return validators;
		}

		
	}
	
	var _init_questionListViewControls = function() {

		/*
		 * Question list view
		 */
		$("#questionListView #addQuestion").unbind('click');
		$("#questionListView #addQuestion").click(function() {
			
			_refreshQuestionView(false);
			_uiManager().show(_questionView(), true, _init_controls);
			
		});
		
		$("#questionListView #removeQuestion").unbind('click');
		$("#questionListView #removeQuestion").click(function() {
			
			if (anyQuestion()) {
				var unit = _questionListView().model;
				unit.remove(_questionListView().selectedItem());
				
				_refreshQuestionListView(unit);
			}
			
		});
		
		$("#questionListView #modifyQuestion").unbind('click');
		$("#questionListView #modifyQuestion").click(function() {

			if (anyQuestion()) {
				var unit = _questionListView().model;
				
				_refreshQuestionView(true, unit.items()[_questionListView().selectedItem()]);
				_uiManager().show(_questionView(), true, _init_controls);
			}
			
		});
		
		function anyQuestion() {
			return  (_questionListView().model != null && _questionListView().model.items().length > 0);
		}
	}
	
	var _init_questionViewControls = function() {
		
		// Question view
		$("#questionView button#saveQuestion").unbind('click');
		$("#questionView button#saveQuestion").click(function() {
			
			$('#questionView form[0]').validationEngine();
			var validData =  Widget.Validator.validate(
					[{'selector': '#questionView #question', 'rules': ['required']},
					 {'selector': '#questionView #answers', 'rules': ['required']}],
					{ 'align': Widget.Feedback.ALIGN_TOP_LEFT }
				);
			
			if (validData) {
				var answers = [];
				var question = $("#questionView #question").val();
				var splited = $("#questionView #answers").val().split('\n');
				for (var i = 0; i < splited.length; i++) {
					if ($.trim(splited[i]).length > 0) {
						answers.push(splited[i]);
					}
				}
				
				var unit = _unitEditView().model;
				
				var item = new Widget.Unit.Item(question, answers);
				if (!_questionView().isEdit()) {
					unit.add(item);
				} else {
					unit.update(_questionListView().selectedItem(), item);
				}
				
				_refreshQuestionListView(unit);
				_uiManager().back(_questionListView(), _init_controls);
			}
		});
		
	}
	
	var _init_challengeViewControls = function() {
		
		$("#challengeView button#checkAnswer").unbind('click');
		$("#challengeView button#checkAnswer").click(function() {
			
			var answer = $("#challengeView #answer").val();
			
			//var correctAnswers = _challengeView().model.challenge.item.answers;
			
			
			var correct = _memorizer().check(answer); 
			var correct = validateAnswer(); 
			if (!correct) {
				_memorizer().incWrong();
			} else {
				_memorizer().incCorrect();
			}
			_challengeView().model.stat = _memorizer().stat(); 
			_challengeView().model.answer = answer;
			
			_refreshChallengeView({'correct': correct}, _challengeView().model);
			if (correct) {
				Widget.Feedback.info('#challengeView #answer', Widget.Messages['Validators.ChallengeView.ValidateAnswer.Correct.text']);
			}
			
			function validateAnswer() {
				$('#challengeView form[0]').validationEngine();
				
				var validators = [];
				validators.push({
					'selector': '#challengeView #answer',
					'rules': [{
						'name': 'challengeView.validateAnswer',
						'type': 'func',
						'fn': validateUserAnswer
					}]
				});
					
				var isValid = Widget.Validator.validate(validators, {
					'align': Widget.Feedback.ALIGN_TOP_LEFT
				});

				function validateUserAnswer() {
					return !_memorizer().check(answer);
				}
				
				return isValid;
			}
			
		});
		
		$("#challengeView button#nextChallenge").unbind('click');
		$("#challengeView button#nextChallenge").click(function() {
			
			_hideFeedbacks();
			_nextChallenge(_challengeView().model.autoChallenge);
			
		});
		$("#challengeView button#closeChallenge").unbind('click');
		$("#challengeView button#closeChallenge").click(function() {
			
			_reSchedule();
			if (_challengeView().model.autoChallenge) {
				if (_config().autoHide()) {
					widget.hide();
				}
			}
			later();
			
		});
		
		$("#challengeView button#stopChallenge").unbind('click');
		$("#challengeView button#stopChallenge").click(function() {
			
			_stopSchedule();
			later();
			
		});
		
		function later() {
			_uiManager().show(_dockedView(), false, _init_controls);
		}

		
	}

	// Initialize the event handlers
	Widget.Control.init = function() {
		
		_init_validationMessages();
		
		// Init controls
		_init_dockedViewControls();
		_init_unitViewControls();
		_init_configViewControls();
		_init_questionViewControls();
		_init_questionListViewControls();
		_init_challengeViewControls();
		
		_refreshDockedView();
		_uiManager().show(_dockedView(), false, _init_controls);		
	}
	
	Widget.Memorizer = function() {
		
		var _unit;
		var _timer;
		var _currentQuestion;
		
		this.unit = function(unit) {
			_unit = unit;
			_timer = null;
			_currentQuestion = null;
		}
		
		this.next = function() {
			var items = _unit.items();
			return _currentQuestion = items[Math.floor(Math.random()*items.length)];
		}
		
		this.check = function(answer) {
			
			return checkAnswer(answer, _currentQuestion.answers);
			
			function checkAnswer(answer, correctAnswers) {
				for (var i = 0; i < correctAnswers.length; i++) {
					if (correctAnswers[i] == answer) {
						return true;
					}
				}
				return false;
			}

			
		}
		
		this.startSchedule = function() {
			if (!_timer) {
				_timer = $.timer(challengeTime(), function() {
					_timer.stop();
					if (_uiManager().current() == _dockedView()) {
						_nextChallenge(true);
						_uiManager().show(_challengeView(), false, _init_controls);
						
						
						// Try to get attention
						widget.show();
						widget.getAttention();
					}
				});
			}
		}
		
		this.reSchedule = function() {
			if (_timer) {
				_timer.reset(challengeTime());
			}
		}
		
		this.stopSchedule = function() {
			if (_timer) {
				_timer.stop();
				_timer = null;
			}
		}
		
		this.isScheduled = function() {
			return _timer;
		}
		
		
		this.stat = function() {
			return _unit.stat();
		}
		
		this.incWrong = function() {
			var stat = _unit.stat();
			stat.wrong += 1;
			_unit.stat(stat);
		}
		
		this.incCorrect = function() {
			var stat = _unit.stat();
			stat.correct += 1;
			_unit.stat(stat);
		}
		
		function challengeTime() {
			return _config().autoChallengeTime() * 1000 * 60;
		}
		
		function _init() {
			Widget.Utils.initializeSingleton(Widget.Memorizer, this);
		}
		
		// Initializer
		_init();

	};
	
	// Static methods & methods
	Widget.Memorizer.instance = function() {
		
		return Widget.Utils.singletonInstance(Widget.Memorizer, true);	
	
	}

	
})();

